package com.pzr.soccer.controller;

import com.pzr.soccer.constans.Consts;
import com.pzr.soccer.io.email.MailService;
import com.pzr.soccer.io.email.ToEmail;
import com.pzr.soccer.io.phone.SendPhoneText;
import com.pzr.soccer.model.*;
import com.pzr.soccer.service.LoginAndRegistryService;
import com.pzr.soccer.service.UserService;
import com.pzr.soccer.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.server.PathParam;
import java.util.Map;

/**
 * @Author pzr
 * @date:2022-01-04-11:36
 * @Description:
 **/
@RestController
@Slf4j
@RequestMapping("/user")
public class UpdateController {

    @Value("${client.name:soccer}")
    private String client;

    @Autowired
    MongoOperations operations;

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    LoginAndRegistryService loginAndRegistryService;
    @Autowired
    UserService userService;

    @Autowired
    SendPhoneText sendPhoneText;

    @Autowired
    MailService mailService;


    @PostMapping("/update")
    public R<User> updateUser(@RequestBody UpdateForm updateForm) {
        String userId = (String) UserUtil.parserUserFromSecurityContext().get("id");
        Map<String, Object> map = updateForm.getPlayLoadMap();
        if (userId == null) {
            return R.fail("get soccer id from security context failed!");
        }
        try {
            User user = userService.updateUser(userId, map);
            return R.ok(user, "update soccer info successfully!please login again!", RT.s(RT.Security_Tag_Update));
        } catch (NoSuchFieldException e) {
            return R.fail("update soccer failed!");
        }
    }

    @PostMapping("/setEmail")
    public R<Object> setEmail(@PathParam("email") String email, @PathParam("code") String code, HttpServletRequest request) {
        String validateCode = (String) redisTemplate.opsForValue().get(Consts.Redis_Email_Code_Prefix + email);
        log.info("code: "+validateCode+" "+code+" "+email);
        if (validateCode == null || !validateCode.equals(code)) {
            return R.fail("验证码错或者已经过期！验证失败");
        }
        String username=null;
        try{
            Map<String, Object> map = UserUtil.parserUserFromSecurityContext();
             username = (String) map.get("username");
            operations.updateFirst(Query.query(Criteria.where("username").is(username)),Update.update("email",email),User.class);
        }catch (Exception e){
            return  R.fail("更新邮箱失败！");
        }
        return logoutAndReLogin(username,request);
    }

    @PostMapping("/setPhone")
    public R<Object> setPhone(@PathParam("password") String password,@PathParam("phone") String phone, @PathParam("code") String code,HttpServletRequest request) {
        String validateCode = (String) redisTemplate.opsForValue().get(Consts.Redis_Phone_Code_Prefix + phone);
        if (validateCode == null || !validateCode.equals(code)) {
            return R.fail("验证码错或者已经过期！");
        }
        String username=null;
        try{
            Map<String, Object> map = UserUtil.parserUserFromSecurityContext();
            username = (String) map.get("username");
            operations.updateFirst(Query.query(Criteria.where("username").is(username)),Update.update("phone",phone),User.class);
        }catch (Exception e){
            return  R.fail("更新手机失败！");
        }
        return logoutAndReLogin(username,request);
    }

    @PostMapping("/setPasswordByPhone")
    public R<Object> setPasswordByPhone(@PathParam("password") String password,@PathParam("phone") String phone, @PathParam("code") String code,HttpServletRequest request) {
        String validateCode = (String) redisTemplate.opsForValue().get(Consts.Redis_Phone_Code_Prefix + phone);
        if (validateCode == null || !validateCode.equals(code)) {
            return R.fail("验证码错或者已经过期！");
        }
        User user=operations.findOne(Query.query(Criteria.where("phone").is(phone)),User.class);
        if(user==null){
            return  R.fail("手机和用户不匹配！");
        }
        user.setPassword(new BCryptPasswordEncoder().encode(password));
        operations.save(user);
        loginAndRegistryService.logout(request);
        return R.ok("更新密码成功！请重新登录！",RT.s(RT.Security_Tag_Logout));
    }

    @PostMapping("/setPasswordByEmail")
    public R<Object> setPasswordByEmail(@PathParam("password") String password,@PathParam("email") String email, @PathParam("code") String code,HttpServletRequest request) {
        String validateCode = (String) redisTemplate.opsForValue().get(Consts.Redis_Email_Code_Prefix + email);
        log.info("code: "+validateCode+" "+code);
        if (validateCode == null || !validateCode.equals(code)) {
            return R.fail("验证码错或者已经过期！");
        }
        User user=operations.findOne(Query.query(Criteria.where("email").is(email)),User.class);
        if(user==null){
            return  R.fail("邮箱和用户不匹配！");
        }
        user.setPassword(new BCryptPasswordEncoder().encode(password));
        operations.save(user);
        loginAndRegistryService.logout(request);
        return R.ok("更新密码成功！请重新登录！",RT.s(RT.Security_Tag_Logout));
    }




    @PostMapping("/fetchUsernameByPhone")
    public R<Object> fetchUsernameByPhone(@PathParam("phone") String phone,@PathParam("code") String code){
        String validateCode = (String) redisTemplate.opsForValue().get(Consts.Redis_Phone_Code_Prefix + phone);
        if (validateCode == null || !validateCode.equals(code)) {
            return R.fail("验证码错或者已经过期！");
        }
        User user = operations.findOne(Query.query(Criteria.where("phone").is(phone)), User.class);
        if(user==null){
            return R.fail("没有该用户！");
        }else {
            int state=sendPhoneText.sentMsgGbk("你的账号名是："+user.getUsername(),phone);
            if(state==1){
                return R.fail("用户名发送到手机，请查收！");
            }else {
                return R.fail("获取用户名失败，因为手机信息发送失败！");
            }
        }
    }

    @PostMapping("/fetchUsernameByEmail")
    public R<Object> fetchUsernameByEmail(@PathParam("email") String email,@PathParam("code") String code){
        String validateCode = (String) redisTemplate.opsForValue().get(Consts.Redis_Email_Code_Prefix + email);
        if (validateCode == null || !validateCode.equals(code)) {
            return R.fail("验证码错或者已经过期！");
        }
        User user = operations.findOne(Query.query(Criteria.where("email").is(email)), User.class);
        if(user==null){
            return R.fail("没有改用户！");
        }else {
            try {
                ToEmail mail=new ToEmail();
                mail.setTo(email);
                mail.setSubject("用户获取用户名回邮");
                mail.setContent("你的账号名是："+user.getUsername());
                mailService.sendHtmlEmail_notAsync(mail);
                return R.ok("发送成功，请查收邮件");
            }catch (Exception e){
                return R.fail("通过邮件获取用户名失败，因为校邮件发送失败:"+e.getMessage());
            }
        }
    }


    private R<Object> logoutAndReLogin(String username,HttpServletRequest request) {
        R<Object> r = null;

        //logout
        try {
            loginAndRegistryService.logout(request);
        } catch (Exception e) {
            return R.ok("用户信息变更成功！请重新登录！");
        }

        //login again
        try {
            LoginResult lr=loginAndRegistryService.reLogin(username);
            if(lr!=null){
                return R.ok(lr,"用户信息变更成功！系统自动重新登录！");
            }else {
                //已经登出，但自动登录不成功！
                return R.ok("用户信息变更成功！请重新登录使其生效！",RT.s(RT.Security_Tag_Logout));
            }

        } catch (Exception e) {
            //已经登出，但自动登录不成功！
            return R.ok("用户信息变更成功！请重新登录使其生效！",RT.s(RT.Security_Tag_Logout));
        }

    }

}
